//
//  GSDKIAPController.m
//  GameSDK
//
//  Created by Johnny on 2017/8/8.
//  Copyright © 2017年 Johnny. All rights reserved.
//

#import "GSDKIAPController.h"
#import "GSDKComplatformBase.h"
#import "GSDKActivityIndicatorView.h"
#import "GSDKCommonMethod.h"
#import "GSDKServicesManager.h"
#import "NSUserDefaults+Extension.h"
#import "GSDKDatabaseManager.h"
#import "YYKit.h"

#define GSDKGOODS @"GSDKGoods"

static GSDKIAPController *shared = nil;

@interface GSDKIAPController() <SKProductsRequestDelegate, SKPaymentTransactionObserver>
@property (nonatomic) BOOL isAppleRestored;     //是否恢复交易
@end

@implementation GSDKIAPController
+ (GSDKIAPController *)shared {
    static dispatch_once_t pred;
    dispatch_once(&pred,^{
        if (shared == nil) {
            shared = [[GSDKIAPController alloc] init];
        }
    });
    return shared;
}

- (id)init {
    self = [super init];
    if (self) {
        [[SKPaymentQueue defaultQueue] addTransactionObserver:self];
    }
    return self;
}

- (void)buyWithGoods:(nonnull GSDKGoods*)goods
          andOrderId:(nonnull NSString *)orderId
        andGameOther:(nonnull NSString *)gameOther
          andSandbox:(BOOL)isSandbox {
    NSArray * transactionArray = [SKPaymentQueue defaultQueue].transactions;
    if (transactionArray.count > 0) {
        SKPaymentTransaction * transaction = [transactionArray firstObject];
        if (transaction.transactionState == SKPaymentTransactionStatePurchased) {
            [[SKPaymentQueue defaultQueue] finishTransaction:transaction];
            return;
        }
    }
    
    _isAppleRestored = false;
    if (GSDKCOMMONMETHOD.accountModel == nil) {
        [[GSDKActivityIndicatorView shared] hide];
        
        GSDKIAPStatus * user = [[GSDKIAPStatus alloc] init];
        user.gSDKIAPStatus = GSDK_IAP_STATUS_PRODUCTBUY;
        GSDKErrorStatus * error = [[GSDKErrorStatus alloc] init];
        error.gSDKErrorStatus = GSDK_ERROR_STATUS_NOLOGIN;
        GSDKMessageStatus * message = [[GSDKMessageStatus alloc] init];
        message.code = @"-1";
        message.msg = [NSString localizedStringForKey:@"GSDK_nologin_error" value:@"没有登录"];
        [[NSNotificationCenter defaultCenter] postNotificationName: GSDKIAPDidFinishNotification object:nil userInfo:@{@"GSDKIAPStatus": user, @"GSDKErrorStatus": error, @"GSDKMessageStatus": message}];
        return;
    }
    GSDKIAPCallBackModel *model = [[GSDKIAPCallBackModel alloc] initIAPCallBackWithSid:GSDKCOMMONMETHOD.GSDKSid andReceipt:@"" andToken:GSDKCOMMONMETHOD.GSDKToken andGameOrderId:orderId andGameOther:gameOther andSandbox:isSandbox ? @"1" : @"0" andGoodsId:goods.goods_id andGoodsName:goods.goods_name andGoodsPrice:goods.goods_price andPayMoney:goods.goods_price andLoginToken:GSDKCOMMONMETHOD.accountModel.token];
    [NSUserDefaults saveValue:[NSKeyedArchiver archivedDataWithRootObject:model] withKey:GSDKGOODS];
    
    NSArray * productArray = [[NSArray alloc]initWithObjects:goods.goods_id, nil];
    NSSet * set = [NSSet setWithArray:productArray];
    SKProductsRequest * request = [[SKProductsRequest alloc]initWithProductIdentifiers:set];
    request.delegate = self;
    [request start];
}

- (void)restored {
    dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(5 * NSEC_PER_SEC)), dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
        NSArray * list = [[GSDKDatabaseManager shared] selectUnfinishedIAP];
        for (GSDKProduct * product in list) {
            if (product.code == 0 && product.model != nil) {
                [[GSDKServicesManager new] iapRequest:product.model andTime:5 andCompletionBlock:^(GSDKResIAPModel *model) {
                    NSArray * list = [[GSDKDatabaseManager shared] selectIAPWith:model.game_order_id];
                    GSDKProduct * product = [list firstObject];
                    if (product != nil) {
                        product.code = 1;
                        product.msg = model.message;
                        [[GSDKDatabaseManager shared] insertIAPWith:product];
                        DEBUGMSG(@"game_order_id = %@, 补单成功", model.game_order_id);
                    }
                }];
            }
        }
    });
}

- (NSArray *)getBuyGoods {
    return [[GSDKDatabaseManager shared] selectAllIAP];
}

//交易结束
- (void)completeTransaction:(SKPaymentTransaction *)transaction {
    DEBUGMSG(@"交易结束");
    //从支付队列中移除交易
    [[SKPaymentQueue defaultQueue] finishTransaction:transaction];
}

/**
 *  base64加密算法
 *
 *  @param input  被加密字符串
 *  @param length 被加密长度
 *
 *  @return 转码后string
 */
- (NSString *)encode:(const uint8_t *)input length:(NSInteger)length {
    static char table[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=";
    NSMutableData *data = [NSMutableData dataWithLength:((length + 2) / 3) * 4];
    uint8_t *output = (uint8_t *)data.mutableBytes;
    for (NSInteger i = 0; i < length; i += 3) {
        NSInteger value = 0;
        for (NSInteger j = i; j < (i + 3); j++) {
            value <<= 8;
            if (j < length) {
                value |= (0xFF & input[j]);
            }
        }
        NSInteger index = (i / 3) * 4;
        output[index + 0] =                    table[(value >> 18) & 0x3F];
        output[index + 1] =                    table[(value >> 12) & 0x3F];
        output[index + 2] = (i + 1) < length ? table[(value >> 6)  & 0x3F] : '=';
        output[index + 3] = (i + 2) < length ? table[(value >> 0)  & 0x3F] : '=';
    }
    return [[NSString alloc] initWithData:data encoding:NSASCIIStringEncoding];
}

#pragma mark - 内购
- (void)productsRequest:(SKProductsRequest *)request didReceiveResponse:(SKProductsResponse *)response {
    NSArray * productArray = response.products;
    if (productArray.count == 0) {
        GSDKIAPStatus * iap = [[GSDKIAPStatus alloc] init];
        iap.gSDKIAPStatus = GSDK_IAP_STATUS_PRODUCTBUY;
        GSDKErrorStatus * error = [[GSDKErrorStatus alloc] init];
        error.gSDKErrorStatus = GSDK_ERROR_STATUS_BUY_NOGOODS;
        GSDKMessageStatus * message = [[GSDKMessageStatus alloc] init];
        message.code = @"-1";
        message.msg = [NSString localizedStringForKey:@"GSDK_noGood_error" value:@"没有这个商品"];
        [[NSNotificationCenter defaultCenter] postNotificationName: GSDKIAPDidFinishNotification object:nil userInfo:@{@"GSDKIAPStatus": iap, @"GSDKErrorStatus": error, @"GSDKMessageStatus": message}];
        [[GSDKActivityIndicatorView shared] hide];
        return ;
    }
    GSDKIAPCallBackModel *model = [NSKeyedUnarchiver unarchiveObjectWithData:[NSUserDefaults getValueIn:GSDKGOODS]];
    SKProduct * product = nil;
    for (SKProduct * p in productArray) {
        if ([model.goods_id isEqualToString:p.productIdentifier]) {
            product = p;
        }
    }
    if (product == nil) {
        GSDKIAPStatus * iap = [[GSDKIAPStatus alloc] init];
        iap.gSDKIAPStatus = GSDK_IAP_STATUS_PRODUCTBUY;
        GSDKErrorStatus * error = [[GSDKErrorStatus alloc] init];
        error.gSDKErrorStatus = GSDK_ERROR_STATUS_BUY_NOGOODS;
        GSDKMessageStatus * message = [[GSDKMessageStatus alloc] init];
        message.code = @"-1";
        message.msg = [NSString localizedStringForKey:@"GSDK_noGood_error" value:@"没有这个商品"];
        [[NSNotificationCenter defaultCenter] postNotificationName: GSDKIAPDidFinishNotification object:nil userInfo:@{@"GSDKIAPStatus": iap, @"GSDKErrorStatus": error, @"GSDKMessageStatus": message}];
        [[GSDKActivityIndicatorView shared] hide];
        return ;
    }
    SKPayment *payment = [SKPayment paymentWithProduct:product];
    DEBUGMSG(@"发送购买请求");
    [[SKPaymentQueue defaultQueue] addPayment:payment];
}

- (void)request:(SKRequest *)request didFailWithError:(NSError *)error {
    GSDKIAPStatus * iap = [[GSDKIAPStatus alloc] init];
    iap.gSDKIAPStatus = GSDK_IAP_STATUS_PRODUCTBUY;
    GSDKErrorStatus * errorS = [[GSDKErrorStatus alloc] init];
    errorS.gSDKErrorStatus = GSDK_ERROR_STATUS_BUY_ERROR;
    GSDKMessageStatus * message = [[GSDKMessageStatus alloc] init];
    message.code = @"-1";
    message.msg = [NSString localizedStringForKey:@"GSDK_buy_error" value:@"购买失败"];
    [[NSNotificationCenter defaultCenter] postNotificationName: GSDKIAPDidFinishNotification object:nil userInfo:@{@"GSDKIAPStatus": iap, @"GSDKErrorStatus": errorS, @"GSDKMessageStatus": message}];
    [[GSDKActivityIndicatorView shared] hide];
}

- (void)paymentQueue:(SKPaymentQueue *)queue updatedTransactions:(NSArray *)transaction {
    for (SKPaymentTransaction * payTrans in transaction) {
        switch (payTrans.transactionState) {
            case SKPaymentTransactionStatePurchasing:
                
                break;
            case SKPaymentTransactionStatePurchased: {
                [self completeTransaction:payTrans];
                NSString *receipt = [self encode:payTrans.transactionReceipt.bytes length:payTrans.transactionReceipt.length];
                GSDKIAPCallBackModel *model = [NSKeyedUnarchiver unarchiveObjectWithData:[NSUserDefaults getValueIn:GSDKGOODS]];
                model.receipt = receipt;
                
                GSDKProduct * product = [GSDKProduct new];
                product.iapID = model.game_order_id;
                product.apid = model.goods_id;
                product.msg = [NSString localizedStringForKey:@"GSDK_order_unauthorized" value:@"此订单未验证"];
                product.postDate = [NSDate date];
                product.userName = GSDKCOMMONMETHOD.accountModel.userName;
                product.model = model;
                product.code = 0;
                product.price = model.pay_money;
                [[GSDKDatabaseManager shared] insertIAPWith:product];
                
                [[GSDKServicesManager new] iapRequest:model andTime:0 andCompletionBlock:^(GSDKResIAPModel *model) {
                    NSArray * list = [[GSDKDatabaseManager shared] selectIAPWith:model.game_order_id];
                    GSDKProduct * product = [list firstObject];
                    if (product != nil) {
                        product.code = 1;
                        product.msg = model.message;
                        [[GSDKDatabaseManager shared] insertIAPWith:product];
                    }
                    GSDKIAPStatus * user = [[GSDKIAPStatus alloc] init];
                    user.gSDKIAPStatus = GSDK_IAP_STATUS_PRODUCTBUY;
                    GSDKMessageStatus * message = [[GSDKMessageStatus alloc] init];
                    message.code = @"0";
                    message.msg = model.message;
                    [[NSNotificationCenter defaultCenter] postNotificationName:GSDKIAPDidFinishNotification object:nil userInfo:@{@"GSDKIAPStatus": user, @"GSDKMessageStatus": message}];
                    [[GSDKActivityIndicatorView shared] hide];
                }];
                break;
            }
            case SKPaymentTransactionStateFailed: {
                [self completeTransaction:payTrans];
                GSDKIAPStatus * iap = [[GSDKIAPStatus alloc] init];
                iap.gSDKIAPStatus = GSDK_IAP_STATUS_PRODUCTBUY;
                GSDKErrorStatus * error = [[GSDKErrorStatus alloc] init];
                error.gSDKErrorStatus = GSDK_ERROR_STATUS_BUY_NOGOODS;
                GSDKMessageStatus * message = [[GSDKMessageStatus alloc] init];
                message.code = @"-1";
                message.msg = [NSString localizedStringForKey:@"GSDK_buy_error" value:@"购买失败"];
                [[NSNotificationCenter defaultCenter] postNotificationName: GSDKIAPDidFinishNotification object:nil userInfo:@{@"GSDKIAPStatus": iap, @"GSDKErrorStatus": error, @"GSDKMessageStatus": message}];
                [[GSDKActivityIndicatorView shared] hide];
                break;
            }
            case SKPaymentTransactionStateRestored:
                break;
            case SKPaymentTransactionStateDeferred:
                break;
        }
    }
}

@end
